﻿#include "stdafx.h"
#include "GraphicScriptBinder.h"
#include "ogre/OgreScriptCompiler.h"
#include "Camera.h"

_NAMESPACE_BEGIN

//////////////////////////////////////////////////////////////////////////

void ConfigDesc::SetDefault()
{
	configs.clear();
	configs["Allow NVPerfHUD"] = "Yes";
	configs["FSAA"] = "0";
	configs["Floating-point mode"] = "Fastest";
	configs["Full Screen"] = "No";
	configs["VSync"] = "No";
	configs["Video Mode"] = "800 x 600 @ 32-bit colour";
	configs["sRGB Gamma Conversion"] = "No";
}

void ConfigDesc::SetConfig( RenderSystem *rSys )
{
	for (hash_map<string,string>::iterator i = configs.begin(); i!=configs.end(); ++i )
	{
		rSys->setConfigOption((*i).first,(*i).second);
	}
}

void ConfigDesc::ReadCfgFile()
{
	if(!cfgFile.Open(L"Config\\OpeningConfig.NRcfg",BECode::OPEN_TYPE_READWRITE))
	{
		cfgFile.Open(L"Config\\OpeningConfig.NRcfg",BECode::OPEN_TYPE_NEW);
	}

	// 新建配置文件
	if (!cfgFile.GetRootNodePtr())
	{
		cfgFile.AddNode("root","Ogre启动配置文件");

		for (hash_map<string,string>::iterator i = configs.begin(); i!=configs.end(); ++i )
		{
			cfgFile.AddNode(i->first,i->second);
		}
	}
	//读取
	else 
	{
		for (hash_map<string,string>::iterator i = configs.begin(); i!=configs.end(); ++i )
		{
			cfgFile.FindNode(i->first);
			cfgFile.Read(i->second);
			cfgFile.ToParent();
		}
	}

	cfgFile.Save();
	cfgFile.Close();
}

//////////////////////////////////////////////////////////////////////////

RenderLib_ScriptBinder::RenderLib_ScriptBinder()
{
	asIScriptEngine* engine=AngelScriptBinder::Instance()->GetEngine();

	int r;

	///Vector3绑定
	Bind_Vector3(engine);
	Bind_OgreProperty(engine);

	///EffectManager
	r = engine->RegisterObjectType("EffectManager",sizeof(EffectManager), asOBJ_REF|asOBJ_NOHANDLE );assert( r >= 0 );
	TYPEMETHODS(EffectManager)
	r = engine->RegisterGlobalProperty("EffectManager Effect_I",EffectManager::Instance() );assert( r >= 0 );

	///ConfigDesc
	r = engine->RegisterObjectType("ConfigDesc",sizeof(ConfigDesc), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_C);assert( r >= 0 );
	TYPEMETHODS(ConfigDesc)

	///OgreProperty
	r = engine->RegisterObjectType("OgreProperty",sizeof(OgreProperty), asOBJ_REF|asOBJ_NOHANDLE );assert( r >= 0 );
	TYPEMETHODS(OgreProperty)
	r = engine->RegisterGlobalProperty("OgreProperty Ogre_I",OgreProperty::Instance() );assert( r >= 0 );

	///OverlayMng
	r = engine->RegisterObjectType("OverlayMng",sizeof(OverlayMng), asOBJ_REF|asOBJ_NOHANDLE );assert( r >= 0 );
	TYPEMETHODS(OverlayMng)
	r = engine->RegisterGlobalProperty("OverlayMng OverlayMng_I",OverlayMng::Instance() );assert( r >= 0 );
}

static void Vector3DefaultConstructor(Vector3 *self)
{
	new(self) Vector3();
}

static void Vector3CopyConstructor(const Vector3 &other, Vector3 *self)
{
	new(self) Vector3(other);
}

static void Vector3InitConstructor(float x, float y, float z, Vector3 *self)
{
	new(self) Vector3(x,y,z);
}

static bool Vector3EqualOperator(const Vector3& self,const Vector3& f2)
{
	return self==f2;
}

static bool Vector3NEqualOperator(const Vector3& self,const Vector3& f2)
{
	return self!=f2;
}

static Vector3 Vector3MulOperator(const Vector3& self,const float f2)
{
	return self*f2;
}

static Vector3 Vector3DivOperator(const Vector3& self,const float f2)
{
	return self/f2;
}

static Vector3 Vector3AddOperator(const Vector3& self,const Vector3& f2)
{
	return self+f2;
}

static Vector3 Vector3MinusOperator(const Vector3& self,const Vector3& f2)
{
	return self-f2;
}

static Overlay* New_Overlay(CONST_REF(string) overlay)
{
	return OverlayManager::getSingleton().getByName(overlay);
}

int RenderLib_ScriptBinder::Bind_Vector3( asIScriptEngine* engine )
{
	int r;
	r = engine->RegisterObjectType("Vector3", sizeof(Vector3), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CA); assert( r >= 0 );

	// 对象属性
	r = engine->RegisterObjectProperty("Vector3", "float x", offsetof(Vector3, x)); assert( r >= 0 );
	r = engine->RegisterObjectProperty("Vector3", "float y", offsetof(Vector3, y)); assert( r >= 0 );
	r = engine->RegisterObjectProperty("Vector3", "float z", offsetof(Vector3, z)); assert( r >= 0 );

	// 运算符重载绑定
	DECLARE_CONSTRUCTOR(Vector3)
	r = engine->RegisterObjectBehaviour("Vector3", asBEHAVE_CONSTRUCT,  "void f(const Vector3 &in)",       asFUNCTION(Vector3CopyConstructor), asCALL_CDECL_OBJLAST); assert( r >= 0 );
	r = engine->RegisterObjectBehaviour("Vector3", asBEHAVE_CONSTRUCT,  "void f(float, float, float)",  asFUNCTION(Vector3InitConstructor), asCALL_CDECL_OBJLAST); assert( r >= 0 );
	r = engine->RegisterObjectMethod("Vector3", "Vector3 &opAddAssign(const Vector3 &in)", asMETHODPR(Vector3, operator+=, (const Vector3&), Vector3&), asCALL_THISCALL); assert( r >= 0 );
	r = engine->RegisterObjectMethod("Vector3", "Vector3 &opSubAssign(const Vector3 &in)", asMETHODPR(Vector3, operator-=, (const Vector3&), Vector3&), asCALL_THISCALL); assert( r >= 0 );
	r = engine->RegisterObjectMethod("Vector3", "Vector3 &opMulAssign(float)", asMETHODPR(Vector3,operator*=,(float), Vector3&), asCALL_THISCALL); assert( r >= 0 );
	r = engine->RegisterObjectMethod("Vector3", "Vector3 &opDivAssign(float)", asMETHODPR(Vector3,operator/=,(float), Vector3&), asCALL_THISCALL); assert( r >= 0 );
	//r = engine->RegisterObjectMethod("Vector3", "Vector3 opNeg() const",asFUNCTION(float3_negate), asCALL_CDECL_OBJLAST); assert( r >= 0 );

	r = engine->RegisterObjectMethod("Vector3", "bool opEquals(const Vector3&in)const",asFUNCTION(Vector3EqualOperator), asCALL_CDECL_OBJFIRST);assert( r >= 0 );
	r = engine->RegisterObjectMethod("Vector3", "Vector3 opMul(float) const",asFUNCTION(Vector3MulOperator), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
	r = engine->RegisterObjectMethod("Vector3", "Vector3 opDiv(float) const",asFUNCTION(Vector3DivOperator), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
	r = engine->RegisterObjectMethod("Vector3", "Vector3 opAdd(const Vector3 &in) const",asFUNCTION(Vector3AddOperator), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
	r = engine->RegisterObjectMethod("Vector3", "Vector3 opSub(const Vector3 &in) const",asFUNCTION(Vector3MinusOperator), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
	//r = engine->RegisterObjectMethod("Vector3","void Cross(const Vector3&in,const Vector3&in)",asFUNCTION(D3DXVec3Cross_Wrap), asCALL_CDECL_OBJLAST);	 assert( r >= 0 );
	//r = engine->RegisterObjectMethod("Vector3","float Dot(const Vector3&in,const Vector3&in)",asFUNCTION(D3DXVec3Dot_Wrap), asCALL_CDECL_OBJLAST);	 assert( r >= 0 );
	r = engine->RegisterObjectMethod("Vector3","float Length()",asMETHOD(Vector3,length), asCALL_THISCALL);	 assert( r >= 0 );
	r = engine->RegisterObjectMethod("Vector3","float Length2()",asMETHOD(Vector3,squaredLength), asCALL_THISCALL);	 assert( r >= 0 );
	r = engine->RegisterObjectMethod("Vector3","void normalize()",asMETHOD(Vector3,normalise), asCALL_THISCALL);	 assert( r >= 0 );
	
	return r;
}

int RenderLib_ScriptBinder::Bind_OgreProperty( asIScriptEngine* engine )
{
	assert(engine);
	
	int r;

	///RenderWindow
	r = engine->RegisterObjectType("RenderWindow",sizeof(RenderWindow), asOBJ_REF);assert( r >= 0 );
	DECLARE_EMPTY_ADD_RELEASE_REF(RenderWindow)
	TYPEMETHODS(RenderWindow)

	///SceneManager
	r = engine->RegisterObjectType("SceneManager",sizeof(SceneManager), asOBJ_REF);assert( r >= 0 );
	DECLARE_EMPTY_ADD_RELEASE_REF(SceneManager)
	TYPEMETHODS(SceneManager)

	///Overlay
	r = engine->RegisterObjectType("Overlay",sizeof(Overlay), asOBJ_REF);assert( r >= 0 );
	DECLARE_EMPTY_ADD_RELEASE_REF(Overlay)
	TYPEMETHODS(Overlay)
	r=engine->RegisterGlobalFunction("Overlay@ New_Overlay(const string&in)",
		asFUNCTION(New_Overlay),asCALL_CDECL);assert( r >= 0 );

	///SceneNode
	r = engine->RegisterObjectType("SceneNode",sizeof(SceneNode), asOBJ_REF);assert( r >= 0 );
	DECLARE_EMPTY_ADD_RELEASE_REF(SceneNode)
	TYPEMETHODS(SceneNode)

	return r;
}

//////////////////////////////////////////////////////////////////////////

void OgreProperty::SetSkyBox( bool enable, CONST_REF(string) name )
{
	sceneManager->setSkyBox(enable,name);
}

void OgreProperty::SetOgreTerrain( CONST_REF(string) name )
{
	sceneManager->setWorldGeometry(name);
}

void OgreProperty::DestoryOgtScene()
{
	ogRoot->TerminateScene();
	SAVE_LOG("销毁场景");
}

void OgreProperty::LoadOgtScene( CONST_REF(string) name )
{
	window->removeAllViewports();
	window->update();

	ogRoot->LoadScene(name);
	SAVE_LOG("加载场景： "+name+" 完成");

	
	sceneManager = ogRoot->GetSceneManager();

	//sceneManager->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_MODULATIVE);
	//sceneManager->setShadowFarDistance(1000);

	CameraCenter::Instance()->Initial(static_cast<Ogre::Viewport*>(ogRoot->GetViewport()->getHandle())->getCamera());

}

Ogre::SceneNode* OgreProperty::GetOgtNode( CONST_REF(string)type, CONST_REF(string)name )
{
	Ogitors::OgitorsRoot* ogr = OgreProperty::Instance()->ogRoot;
	Ogitors::NameObjectPairList pairList = ogr->GetObjectsByTypeName(type);
	Ogitors::CBaseEditor* edt = pairList[name];
	return edt->getNode();
}

void OgreProperty::CompileScript( CONST_REF(string)code)
{

	Ogre::String script = code;
	Ogre::MemoryDataStream *memoryStream = new Ogre::MemoryDataStream((void*)script.c_str(), script.length() * sizeof(char));
	Ogre::DataStreamPtr dataStream(memoryStream);
	
	Ogre::ScriptCompilerManager::getSingleton().parseScript(dataStream, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
	//Ogre::StringVector lines = Ogre::StringUtil::split(script, "\n");
	//for(Ogre::StringVector::iterator line = lines.begin(); line != lines.end(); line++)
	//{
	//	Ogre::StringVector params = Ogre::StringUtil::split(*line, " \t:");
	//	if (params[0] == "material")
	//	{
	//		Ogre::String materialName = params[1];
	//		Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().getByName(materialName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
	//		material->compile();
	//	}
	//}
}

OgreProperty::OgreProperty() :sceneManager(NULL),window(NULL)
{
//	compiler  = new Ogre::ScriptCompiler;
}

OgreProperty::~OgreProperty()
{
//	SAFEDELETE(compiler);
	sceneManager = NULL;
	window = NULL;
}

void OgreProperty::CompileOverlayScript( CONST_REF(string)code )
{
	Ogre::String script = code;
	Ogre::MemoryDataStream *memoryStream = new Ogre::MemoryDataStream((void*)script.c_str(), script.length() * sizeof(char));
	Ogre::DataStreamPtr dataStream(memoryStream);

	Ogre::OverlayManager::getSingleton().parseScript(dataStream, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
}

void OgreProperty::GetNodePos( SceneNode* node , Vector3& out )
{
	out = node->getPosition();
}

void OgreProperty::GetOgtNodePos( CONST_REF(string)type,CONST_REF(string)name,Vector3&out )
{
	out = GetOgtNode(type,name)->getPosition();
}

_NAMESPACE_END


